package com.wenlin.myproduction.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.wenlin.myproduction.R;
import com.wenlin.myproduction.bean.ActivityBean;
import com.wenlin.myproduction.util.Checker;
import com.wenlin.myproduction.util.ToastUtils;
import com.wenlin.myproduction.util.TypeData;
import com.wenlin.myproduction.util.TypeDataNames;
import com.wenlin.myproduction.util.UI;
import com.wenlin.myproduction.util.UserManage;

import org.greenrobot.eventbus.EventBus;

import java.util.List;
import java.util.concurrent.ExecutionException;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * 转盘抽奖控件
 */
public class LotteryCircleView extends View implements Runnable {
    private final static int STATE_NORMAL = 0;
    private final static int STATE_SELECTED = 1;
    private final static int COST_COUPON = 2;
    private final static float TARGET_SPEED = 32f;
    private static final int DELAY = 16;
    private int viewWidth = (int) UI.getPx(R.dimen.wpx1200);
    private int viewHeight = (int) UI.getPx(R.dimen.wpx1744);
    private float marginFromCenterY = (int) UI.getPx(R.dimen.wpx580);
    private Paint paint;
    private TextPaint textPaint;
    private Matrix mMatrix = new Matrix();  // 奖项图标绘制的位置矩阵
    private RectF rectCircle, rectF;
    private float radius = UI.getPx(R.dimen.wpx431);//圆盘半径
    private Bitmap bitmapBg, bitmapTitle, bitmapArrow, bitmapBtn;
    private List<ActivityBean.ActivityGiftBean> list;
    private float current;//当前转过的角度
    private float target = TARGET_SPEED;//目标速度
    private float acceleration = 16f;//加速度
    private float speed = 0f;//当前速度
    private boolean isRolling = false;//是否转动中
    private float itemAngle;//每个奖品的角度
    private int[] arrColor = {Color.parseColor("#FFE07AFE"),
            Color.parseColor("#FFD9318A"),
            Color.parseColor("#FFE85396"),
            Color.parseColor("#FFF58691"),
            Color.parseColor("#FFF6C949"),
            Color.parseColor("#FF2ACAEB"),
            Color.parseColor("#FF35ACFA"),
            Color.parseColor("#FFBE5AFA")};
    private LotteryListener listener;
    private int state;//状态
    private boolean btnEnable;//按钮是否可按
    private int targetRewardIndex;//未来指向的目标奖品的位置
    private boolean isFail;//因故失败，不走弹礼物弹窗的流程
    private int cost = COST_COUPON;
    private boolean dailyTask;//是否是每日任务的抽奖
    private Bitmap bitmapDefault;

    public LotteryCircleView(Context context) {
        this(context, null);
    }

    public LotteryCircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    /**
     * 初始化
     */
    private void initialize() {
        //画笔初始化
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        textPaint = new TextPaint();
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setColor(Color.WHITE);
        textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        textPaint.setTextSize(UI.getPx(R.dimen.wpx45));
        textPaint.setFakeBoldText(true);
        //位图初始化
        bitmapBg = BitmapFactory.decodeResource(getResources(), R.mipmap.lottery_ic_bg_circle);
        bitmapBg = handleBitmap(bitmapBg, UI.getPx(R.dimen.wpx1200), UI.getPx(R.dimen.wpx1744));
        bitmapTitle = BitmapFactory.decodeResource(getResources(), R.mipmap.lottery_ic_title);
        bitmapTitle = handleBitmap(bitmapTitle, UI.getPx(R.dimen.wpx793), UI.getPx(R.dimen.wpx222));
        bitmapArrow = BitmapFactory.decodeResource(getResources(), R.mipmap.lottery_ic_arrow);
        bitmapArrow = handleBitmap(bitmapArrow, UI.getPx(R.dimen.wpx240), UI.getPx(R.dimen.wpx294));
        bitmapDefault = BitmapFactory.decodeResource(getResources(), R.mipmap.lottery_ic_gift_placeholder);
        bitmapDefault = handleBitmap(bitmapDefault, UI.getPx(R.dimen.wpx331), UI.getPx(R.dimen.wpx330));
        //其他初始化
        rectF = new RectF();
        rectCircle = new RectF();
        rectCircle.set(viewWidth / 2f - radius, viewHeight / 2f - radius, viewWidth / 2f + radius, viewHeight / 2f + radius);
    }

    /**
     * 设置奖品的数据集合
     *
     * @param list 奖品集合
     */
    public void setData(List<ActivityBean.ActivityGiftBean> list) {
        this.list = list;
        btnEnable = true;
        if (Checker.hasList(list) && list.size() >= 1) itemAngle = 360f / list.size();
        handleGiftBitmap();
    }

    /**
     * 处理奖品位图
     */
    private void handleGiftBitmap() {
        for (int i = 0; i < list.size(); i++) {
            ActivityBean.ActivityGiftBean agb = list.get(i);
            Observable.just(agb.GiftPic).map(url -> {
                Bitmap bitmap = null;
                try {
                    bitmap = Glide.with(getContext()).asBitmap().load(url).submit().get();
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }
                return bitmap;
            }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Bitmap>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    ToastUtils.getInstance().showInfo("奖品图片异常，无法抽奖");
                    EventBus.getDefault().post(new TypeData<>(TypeDataNames.finishLotteryActivity, true));
                }

                @Override
                public void onNext(Bitmap bitmap) {
                    if (bitmap == null) {
                        ToastUtils.getInstance().showInfo("奖品图片异常，无法抽奖");
                        EventBus.getDefault().post(new TypeData<>(TypeDataNames.finishLotteryActivity, true));
                        return;
                    }
                    if (Checker.hasList(list)) {
                        for (int j = 0; j < list.size(); j++) {
                            ActivityBean.ActivityGiftBean temp = list.get(j);
                            if (temp.GiftPic.equals(agb.GiftPic)) {
                                list.get(j).Bitmap = handleBitmap(bitmap, UI.getPx(R.dimen.wpx330), UI.getPx(R.dimen.wpx330));
                                break;
                            }
                        }
                    }
                    postInvalidate();
                }
            });
        }
    }

    /**
     * 设置
     *
     * @param dailyTask 是否是每日任务抽奖
     * @param cost      消耗兑换券数量
     */
    public void init(boolean dailyTask, int cost) {
        this.dailyTask = dailyTask;
        this.cost = dailyTask ? 0 : cost;
        bitmapBtn = BitmapFactory.decodeResource(getResources(), dailyTask ? R.mipmap.lottery_ic_btn_without_coupon : R.mipmap.lottery_ic_btn);
        bitmapBtn = handleBitmap(bitmapBtn, UI.getPx(R.dimen.wpx681), UI.getPx(R.dimen.wpx320));
        invalidate();
    }

    /**
     * 设置监听
     *
     * @param listener 监听器
     */
    public void setListener(LotteryListener listener) {
        this.listener = listener;
    }

    /**
     * 开始旋转
     */
    public void setGetCodeAndStartFlash() {
        btnEnable = false;
        listener.onSetReward();
        target = TARGET_SPEED;
        if (speed == 0) {
            acceleration = Math.abs(target - speed) / 100f;  // 设定1600秒达到最大速度，算出加速度
            isRolling = true;
            postDelayed(this, DELAY);
        }
    }

    /**
     * 设置中奖的奖品
     *
     * @param targetReward 奖品
     */
    public void setTargetGift(ActivityBean.ActivityGiftBean targetReward) {
        if (Checker.hasList(list)) {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).GiftId == targetReward.GiftId) {
                    targetRewardIndex = i;
                    onStopping();
                    break;
                }
            }
        }
    }

    /**
     * 停止到指定位置
     */
    private void onStopping() {
        isFail = false;
        postDelayed(this::onStop, 2400);
    }

    /**
     * 终止
     */
    public void onAbort() {
        isFail = true;
        removeCallbacks(this);
        isRolling = false;
        target = 0;
        speed = 0;
        current = 0;
        btnEnable = true;
        postInvalidate();
    }

    /**
     * 停止
     */
    private void onStop() {
        removeCallbacks(this);
        isRolling = false;
        // 根据速度计算还要转动多少圈，外加当前奖项起始角度，奖项内随机角度
        int times = (int) (speed / 3f) * 360 + 360;//speed下的是阻尼，取3~5
        float random = itemAngle * (float) (Math.random() - 0.5d) * 0.45f;
        float distance = times - itemAngle * targetRewardIndex - itemAngle / 2f + random;
        float n = 2f * (distance - current) / speed;
        acceleration = speed / (n - 1);
        target = 0;
        isRolling = true;
        run();
    }

    @Override
    public void run() {
        if (!isRolling) {
            return;
        }
        current = (current + speed) % 360;
        invalidate();   // 转盘转动一次
        if (speed < target && speed + acceleration > target) {
            speed = target;   // 速度比目标速度小，并且不足一次加速
            postDelayed(this, DELAY);
            return;
        }
        if (speed > target && speed - acceleration < target) {
            speed = target;   // 速度比目标速度大，并且不足一次加速
            postDelayed(this, DELAY);
            return;
        }
        if (speed < target) { // 速度比目标速度小
            speed = speed + acceleration;
            postDelayed(this, DELAY);
            return;
        }
        if (speed > target) { // 速度比目标速度大
            speed = speed - acceleration;
            postDelayed(this, DELAY);
            return;
        }
        if (speed > 0) {
            postDelayed(this, DELAY);
        } else {
            if (!isFail) {
                if (Checker.notNull(listener)) listener.onSelected(list.get(targetRewardIndex));
            }
            btnEnable = true;
            target = TARGET_SPEED;
        }
    }

    /**
     * 生成新的Bitmap图片
     *
     * @return 所求
     */
    private Bitmap handleBitmap(Bitmap bitmap, float newWidth, float newHeight) {
        Matrix matrix = new Matrix();//创建一个处理图片的类
        int width = bitmap.getWidth();//获取图片本身的大小(宽)
        int height = bitmap.getHeight();//获取图片本身的大小(高)
        float wS = newWidth / width;//缩放比---->这块注意这个是新的宽度/高度除以旧的宽度
        float hS = newHeight / height;//缩放比---->这块注意这个是新的宽度/高度除以旧的宽度
        matrix.postScale(wS, hS);//这块就是处理缩放的比例
        //matrix.setScale(sX,sY);//缩放图片的质量sX表示宽0.5就代表缩放一半,sX同样
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        rectF.set(viewWidth / 2f - bitmapBg.getWidth() / 2f, viewHeight / 2f - bitmapBg.getHeight() / 2f, viewWidth / 2f + bitmapBg.getWidth() / 2f, viewHeight / 2f + bitmapBg.getHeight() / 2f);
        canvas.drawBitmap(bitmapBg, null, rectF, paint);
        if (Checker.hasList(list)) {
            for (int i = 0; i < list.size(); i++) {
                float angle = current + itemAngle * i;
                paint.setColor(arrColor[i % arrColor.length]);
                canvas.drawArc(rectCircle, angle, itemAngle, true, paint);    // 绘制圆盘奖项背景色
            }
            for (int i = 0; i < list.size(); i++) {
                ActivityBean.ActivityGiftBean rewardBean = list.get(i);
                float angle2 = current + itemAngle * i + itemAngle / 2f;
                //画图
                float rectify = -90f;
                double radian = (double) (angle2 + rectify) / 180d * Math.PI;
                double x = viewWidth / 2f + radius * 63 / 100 * Math.cos(radian);
                double y = viewHeight / 2f + radius * 63 / 100 * Math.sin(radian);
                Bitmap bitmap = rewardBean.Bitmap;
                if (Checker.isNull(bitmap)) bitmap = bitmapDefault;
                float dx = (float) x - (float) bitmap.getWidth() / 2f;
                float dy = (float) y - (float) bitmap.getHeight() / 2f;
                mMatrix.reset();
                mMatrix.postRotate(angle2, bitmap.getWidth() / 2f, bitmap.getHeight() / 2f);
                mMatrix.postTranslate(dx, dy);
                canvas.drawBitmap(bitmap, mMatrix, null);
            }
        }
        rectF.set(viewWidth / 2f - bitmapTitle.getWidth() / 2f, viewHeight / 2f - UI.getPx(R.dimen.wpx533) - bitmapTitle.getHeight(), viewWidth / 2f + bitmapTitle.getWidth() / 2f, viewHeight / 2f - UI.getPx(R.dimen.wpx533));
        canvas.drawBitmap(bitmapTitle, null, rectF, paint);
        rectF.set(viewWidth / 2f - bitmapArrow.getWidth() / 2f, viewHeight / 2f + UI.getPx(R.dimen.wpx120) - bitmapArrow.getHeight(), viewWidth / 2f + bitmapArrow.getWidth() / 2f, viewHeight / 2f + UI.getPx(R.dimen.wpx120));
        canvas.drawBitmap(bitmapArrow, null, rectF, paint);
        rectF.set(viewWidth / 2f - bitmapBtn.getWidth() / 2f, viewHeight / 2f + marginFromCenterY, viewWidth / 2f + bitmapBtn.getWidth() / 2f, viewHeight / 2f + marginFromCenterY + bitmapBtn.getHeight());
        canvas.drawBitmap(bitmapBtn, null, rectF, paint);
        if (!dailyTask)
            canvas.drawText(String.valueOf(cost), viewWidth / 2f + UI.getPx(R.dimen.wpx108), viewHeight / 2f + UI.getPx(R.dimen.wpx718), textPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        float x = event.getX();
        float y = event.getY();
        if (!btnEnable) return true;//如果按钮不能按，则直接返回true
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (actionDownInButton(x, y)) {
                    state = STATE_SELECTED;
                    invalidate();
                    return true;
                } else {
                    return false;
                }
            case MotionEvent.ACTION_MOVE:
                if (state == STATE_SELECTED && actionDownInButton(x, y)) {
                    invalidate();
                    return true;
                }
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                state = STATE_NORMAL;
                if (actionDownInButton(x, y)) {
                    if (cost > UserManage.getInstance().getCouponCount()) {
                        ToastUtils.getInstance().showInfo( "兑换券不够，请坚持每日打卡");
                    } else {
                        if (Checker.notNull(listener)) {
                            listener.onGetCode();
                        }
                    }
                }
                invalidate();
                performClick();
                return true;
            default:
        }
        return super.onTouchEvent(event);
    }

    /**
     * 动作按下的坐标是否在按钮里面——是否点击了按钮
     *
     * @param x 横坐标
     * @param y 纵坐标
     * @return 所求
     */
    private boolean actionDownInButton(float x, float y) {
        return x > viewWidth / 2f - bitmapBtn.getWidth() / 2f + UI.getPx(R.dimen.wpx90)//90是左边距，因为按钮图片是有黑色半透阴影的，所以为了得到按钮主体的宽高需要bitmap的宽高减去四面的边距
                && x < viewWidth / 2f + bitmapBtn.getWidth() / 2f - UI.getPx(R.dimen.wpx90)//90是右边距
                && y > viewHeight / 2f + marginFromCenterY + UI.getPx(R.dimen.wpx50)//50是上边距
                && y < viewHeight / 2f + marginFromCenterY + bitmapBtn.getHeight() - UI.getPx(R.dimen.wpx110);//110是下边距
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        removeCallbacks(this);
        speed = 0;
        if (Checker.notNull(bitmapBg) && !bitmapBg.isRecycled()) {
            bitmapBg.recycle();
            bitmapBg = null;
        }
        if (Checker.notNull(bitmapTitle) && !bitmapTitle.isRecycled()) {
            bitmapTitle.recycle();
            bitmapTitle = null;
        }
        if (Checker.notNull(bitmapArrow) && !bitmapArrow.isRecycled()) {
            bitmapArrow.recycle();
            bitmapArrow = null;
        }
        if (Checker.notNull(bitmapDefault) && !bitmapDefault.isRecycled()) {
            bitmapDefault.recycle();
            bitmapDefault = null;
        }
        if (Checker.notNull(bitmapBtn) && !bitmapBtn.isRecycled()) {
            bitmapBtn.recycle();
            bitmapBtn = null;
        }
        //释放bitmap
        if (Checker.hasList(list)) {
            for (int i = 0; i < list.size(); i++) {
                ActivityBean.ActivityGiftBean bean = list.get(i);
                Bitmap bitmap = bean.Bitmap;
                if (bitmap != null && !bitmap.isRecycled()) {
                    bitmap.recycle();
                    bitmap = null;
                    list.get(i).Bitmap = null;
                }
            }
            list.clear();
            list = null;
        }
    }

    public interface LotteryListener {
        void onSelected(ActivityBean.ActivityGiftBean activityGiftBean);//绕圈闪动之后停在了该奖品上

        void onSetReward();//去通过数据接口来设置最终的奖品是哪个

        void onGetCode();//第一次点击按钮时，先弹窗去获取验证码
    }
}
